package com.hccl.config;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import io.github.ganchix.morphia.utils.MorphiaUtils;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.Morphia;
import org.mongodb.morphia.annotations.Entity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.mongodb.core.MongoTemplate;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * AutoConfiguration class.
 * <p>
 * Created by Rafa on 05/04/17.
 */
@Configuration
//@AutoConfigureAfter(MongoAutoConfiguration.class)
public class MorphiaAutoConfiguration {
//    @Autowired
//    private MongoClient mongoClient;
//    @Autowired
//    private MongoTemplate mongoTemplate;

    private String DB_ADRESS;
    private int DB_PORT;
    private String DB_NAME;
    private String DB_USER;
    private String DB_PASSWORD;
    private String DB_ADDRESSLIST;


    @Autowired
    private ApplicationContext applicationContext;


    @Bean
    Morphia morphia() {
        return new Morphia();
    }

    @Bean
    public Datastore datastore(Morphia morphia) throws ClassNotFoundException, IOException {

        List<String> packageNamesFromApplication = MorphiaUtils.getApplicationPackageName(applicationContext);

        Set<Class<?>> classes = packageNamesFromApplication
                .parallelStream()
                .flatMap(packageName -> MorphiaUtils.getClasses(packageName).parallelStream())
                .collect(Collectors.toSet());

        classes.parallelStream()
                .filter(clazz -> Objects.nonNull(clazz.getAnnotation(Entity.class)))
                .forEach(clazz -> morphia.map(clazz));

        Properties property=new Properties();
        property.load(new FileInputStream("application.properties"));
        //支持连接单机和集群
        MongoClient mongoClient;
        Datastore dataStore = null;
        MongoClientOptions mongoOptions = MongoClientOptions.builder().socketTimeout(1200)
                .connectTimeout(1200).build(); // SocketTimeout: 60s, ConnectionTimeout: 20min
        DB_USER = property.getProperty("mongodb_username");
        DB_NAME = property.getProperty("mongodb_database");
        DB_PASSWORD = property.getProperty("mongodb_password");
        DB_ADDRESSLIST = property.getProperty("mongodb_addressList");
        if (DB_ADDRESSLIST == null) {//如果地址list为空就连接单机
            DB_ADRESS = property.getProperty("mongodb_host");
            DB_PORT = Integer.valueOf(property.getProperty("mongodb_port")).intValue();
            if (DB_USER==null){//无密码
               mongoClient = new MongoClient( DB_ADRESS, DB_PORT );
            }else {
                MongoCredential credential = MongoCredential.createMongoCRCredential(DB_USER, DB_NAME, DB_PASSWORD.toCharArray());
                mongoClient = new MongoClient(new ServerAddress(DB_ADRESS, DB_PORT), Arrays.asList(credential), mongoOptions);
            }
            dataStore = morphia.createDatastore(mongoClient, DB_NAME);
        } else {//连接集群
            List<String> addressStringList = Arrays.asList(DB_ADDRESSLIST.split(","));
            //将字符串列表转换成ServerAddress列表
            List<ServerAddress> t = addressStringList.stream().map(x -> {
                return new ServerAddress(x);
            }).collect(Collectors.toList());
            if (DB_USER==null){//无密码
                mongoClient = new MongoClient(t, mongoOptions);
            }else { //有密码
                MongoCredential credential = MongoCredential.createScramSha1Credential(DB_USER, DB_NAME, DB_PASSWORD.toCharArray());
                mongoClient = new MongoClient(t, Arrays.asList(credential), mongoOptions);
            }
            dataStore = morphia.createDatastore(mongoClient, DB_NAME);
        }
        dataStore.ensureIndexes();
        return dataStore;
    }


}

